using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using XmlDataType;
using ObjectLibrary;
using AIProcessor;
using Particle3DEffect;
using FighterLibrary;

namespace _0912089_0912172
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class PlayingScreen : Microsoft.Xna.Framework.DrawableGameComponent
    {
        #region Field
        public enum CAMERA_TYPE { THIRD_PERSON, ROTATION, AUTO_ROTATION, FIRST_PERSON };
        public enum GAME_STATE {FREEZE, BEGIN,PLAY,PAUSE,END };
        string[][] FighterResouces = new string[][]{
                new string[]{ @"Resources/Models/Cat/WhiteCat/Cat", @"Resources/Models/Cat/BlackCat/Cat"}
                 
            };
        CAMERA_TYPE cameraType;
        bool escPressed = false;
        Radar gameRadar;
        Bar hpBar;
        Bar ppBar;
        SpriteBatch spriteBatch;
        MyCamera camera;
        NormalPerspectiveCamera thirdPersonCamera;
        FirstPersonCamera firstPersonCamera;
        RotationPerspectiveCamera rotationCamera;
        AutoRotationPerspectiveCamera autoRotationCamera;
        MotionCamera motionCamera;
        BasicEffect effect;
        MyCursor cursor;
        KeyboardState currentKeyboardState = new KeyboardState();
        GamePadState currentGamePadState = new GamePadState();
        Sprite2D panel;
        Sprite2D tablePanel;
        Sprite2D yesButton;
        Sprite2D noButton;
        Sprite2D reSultSprite;
        Color hoverButtonColor = Color.White;
        Color buttonColor = new Color(0.6f, 0.6f, 0.6f, 0.6f);

        Random gameRandom;
        Fighter player;
        My3DModel skyDom;

        Sprite2D aimCursor;
        bool isDraggedLeftMouse = false;
        bool isDraggedRightMouse = false;
        bool isDraggedMidMouse = false;
        int preScrollWheelValue;
        int widthScreen;
        int heightScreen;
        bool flag = true;
        bool modeDrawingBoundingSphere = false;
        bool isBoundingKeyClicked = false;
        bool isTabPressed;

        int _team;
        float modeDamageRatio;
        Map terrainMap;
        SpriteFont font;
        MapInfo _mapInfo;
        Word gameWord;
        List<ComputerControl> computerAIControl;
        int _teamAPoint;
        int _teamBPoint;
        int _victoryPoint = 10;

        public int VictoryPoint
        {
            get { return _victoryPoint; }
            set { _victoryPoint = value; }
        }

        private List<Fighter> _teamA;
        private List<Fighter> _teamB;
        private List<Vector3> _explosionPoint;
        //private List<> _explosionPoint;

        double timeDragLeftMouse = 0;
        double playingTime = 0;
        int limitSecondGameTime =-1;

        double timeSpanThrowEnergySphere = 500;
        double currentTimeThrowEnergySphere = 0;

        public int LimitSecondGameTime
        {
            get { return limitSecondGameTime; }
            set { limitSecondGameTime = value; }
        }
        GAME_STATE gameState;

        Vector2 tableStart1;
        Vector2 tableStart2;
        Vector2 tableTab1;
        Vector2 tableTab2;


        // This sample uses five different particle systems.
        ParticleSystem explosionParticles;
        ParticleSystem explosionSmokeParticles;
        ParticleSystem projectileTrailParticles;
        ParticleSystem smokePlumeParticles;
        ParticleSystem fireParticles;
        ParticleSystem shieldParticles;

        PARTICLE_STATE currentState = PARTICLE_STATE.SHIELD;

        // The explosions effect works by firing projectiles up into the
        // air, so we need to keep track of all the active projectiles.
        List<Projectile> projectiles = new List<Projectile>();

        TimeSpan timeToNextProjectile = TimeSpan.Zero;


        #endregion

        #region Init
        public PlayingScreen(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
        }
        
        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        /// 
        public override void Initialize()
        {
            // TODO: Add your initialization code here
            base.Initialize();
            widthScreen = GraphicsDevice.Viewport.Width;
            heightScreen = GraphicsDevice.Viewport.Height;

            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            font = Game.Content.Load<SpriteFont>(@"Resources/System/Font");
            cursor = new MyCursor(Game.Content);
            cursor.Visible = false;
            TextureUntity textureUntity = TextureUntity.Create(Game.Content, Game.GraphicsDevice);
            tableStart1 = new Vector2(widthScreen/3,heightScreen/8 + 50);
            tableStart2 = new Vector2(widthScreen / 3, heightScreen / 2 +50 );
            tableTab1 = new Vector2(2*widthScreen /3 - 100, heightScreen / 8);
            tableTab2 = new Vector2(2*widthScreen / 3 -50, heightScreen / 8);
            tablePanel = new Sprite2D(textureUntity.createTexture(widthScreen / 2, 3*heightScreen / 4+100, new Color(0, 0.3f, 0.1f, 0.8f)),
                new Vector2(widthScreen / 2, heightScreen / 2), true);
            panel = new Sprite2D(textureUntity.createTexture(widthScreen / 2, heightScreen / 3, heightScreen / 10, new Color(0, 0.3f, 0.1f, 0.8f)),
                new Vector2(widthScreen / 2, heightScreen / 2), true);

            yesButton = new Sprite2D(Game.Content, @"Resources/InGame2DResources/YesButton",
                new Vector2(widthScreen / 2 - 80, heightScreen / 2 + 30), true);

            noButton = new Sprite2D(Game.Content, @"Resources/InGame2DResources/NoButton",
                new Vector2(widthScreen / 2 + 80, heightScreen / 2 + 30), true);

            reSultSprite = new Sprite2D(Game.Content, @"Resources/InGame2DResources/Win", new Vector2(widthScreen / 2, heightScreen / 2), true);


            camera = new MyCamera();
            thirdPersonCamera = new NormalPerspectiveCamera();
            firstPersonCamera = new FirstPersonCamera();
            rotationCamera = new RotationPerspectiveCamera();
            autoRotationCamera = new AutoRotationPerspectiveCamera();
            motionCamera = new MotionCamera();

            thirdPersonCamera.initCamera(
                new Vector3(0, 100, 120),
                new Vector3(0, 0, 0),
                new Vector3(0, 1, 0),
                1f,
                1000f,
                MathHelper.PiOver4,
                widthScreen / heightScreen);
            firstPersonCamera.initCamera(
                new Vector3(0, 100, 120),
                new Vector3(0, 0, 0),
                new Vector3(0, 1, 0),
                1f,
                1000f,
                MathHelper.PiOver4,
                widthScreen / heightScreen);
            rotationCamera.initCamera(
                new Vector3(0, 100, 120),
                new Vector3(0, 0, 0),
                new Vector3(0, 1, 0),
                1f,
                1000f,
                MathHelper.PiOver4,
                widthScreen / heightScreen);
            autoRotationCamera.initCamera(
                new Vector3(0, 100, 120),
                new Vector3(0, 0, 0),
                new Vector3(0, 1, 0),
                1f,
                1000f,
                MathHelper.PiOver4,
                widthScreen / heightScreen);
            
            cameraType = CAMERA_TYPE.THIRD_PERSON;
            camera = thirdPersonCamera;

            effect = new BasicEffect(GraphicsDevice);
            gameRadar = new Radar(Game.Content, 100);
            hpBar = new Bar(Game.Content, Game.GraphicsDevice
                , @"Resources/InGame2DResources/DisHPBar", @"Resources/InGame2DResources/HPBar", Bar.BAR_TYPE.UP_DOWN);
            ppBar = new Bar(Game.Content, Game.GraphicsDevice
                , @"Resources/InGame2DResources/DisPPBar", @"Resources/InGame2DResources/PPBar", Bar.BAR_TYPE.QUATER_CIRCLE);
            aimCursor = new Sprite2D(Game.Content, @"Resources/InGame2DResources/Cursor", new Vector2(widthScreen / 2, heightScreen / 2), true);

            computerAIControl = new List<ComputerControl>();

            _teamA = new List<Fighter>();
            _teamB = new List<Fighter>();
            _explosionPoint = new List<Vector3>();
            // Load the model.
            initMap("Map01");
            modeDamageRatio = 0.4f;
            gameState = GAME_STATE.FREEZE;
            gameRandom = new Random();
            
            //initParticle3DEffect();
        }

        private void initParticle3DEffect()
        {
            // Construct our particle system components.
            explosionParticles = new ExplosionParticleSystem(Game, Game.Content);
            explosionSmokeParticles = new ExplosionSmokeParticleSystem(Game, Game.Content);
            projectileTrailParticles = new ProjectileTrailParticleSystem(Game, Game.Content);
            smokePlumeParticles = new SmokePlumeParticleSystem(Game, Game.Content);
            fireParticles = new FireParticleSystem(Game, Game.Content);
            shieldParticles = new EnergySphereParticle(Game, Game.Content);

            // Set the draw order so the explosions and fire
            // will appear over the top of the smoke.
            smokePlumeParticles.DrawOrder = 100;
            explosionSmokeParticles.DrawOrder = 200;
            projectileTrailParticles.DrawOrder = 300;
            explosionParticles.DrawOrder = 400;
            fireParticles.DrawOrder = 500;
            shieldParticles.DrawOrder = 600;

            // Register the particle system components.
            Game.Components.Add(explosionParticles);
            Game.Components.Add(explosionSmokeParticles);
            Game.Components.Add(projectileTrailParticles);
            Game.Components.Add(smokePlumeParticles);
            Game.Components.Add(fireParticles);
            Game.Components.Add(shieldParticles);
        }

        public void addPlayer(int team, int type, string name, bool isPlayerControl, int level)
        {
            Fighter newFighter;
            //Aura aura;
            if (type < 0 || type >= FighterResouces.Length || team < 0 || team >= FighterResouces[type].Length)
            {
                return;
            }
            //if (team == 0)
            //    aura = new Aura(Game.Content, @"Resources/Aura/aura", 0.5f, Vector3.Zero, Matrix.CreateRotationX(-MathHelper.PiOver2));
            //else
            //    aura = new Aura(Game.Content, @"Resources/Aura/aura1", 2f, Vector3.Zero, Matrix.CreateRotationX(-MathHelper.PiOver2));

            if (type == 0)
            {
                newFighter = new CatFighter(Game.Content, FighterResouces[type][team]);
            }
            else
            {
                newFighter = new BearFighter(Game.Content, FighterResouces[type][team]);
            }

            //newFighter.Aura = aura;
            //newFighter.Position = new Vector3((int)(gameRandom.NextDouble() * 50) , 0, (int)(gameRandom.NextDouble() * 50) );
            //newFighter.Position = new Vector3((int)(gameRandom.NextDouble() * 100) - 50, 0, (int)(gameRandom.NextDouble() * 100) - 50);
            int nPosition = terrainMap.HomeAPositions.Count;
            Vector2 pos2D;
            if (team == 0)
            {
                _teamA.Add(newFighter);
                pos2D = terrainMap.HomeAPositions[gameRandom.Next() % nPosition];
            }
            else
            {
                _teamB.Add(newFighter);
                pos2D = terrainMap.HomeBPositions[gameRandom.Next() % nPosition];
            }
            newFighter.Name = name;
            newFighter.Idle();
            Vector3 pos3D = new Vector3(pos2D.X, 0, pos2D.Y);
            newFighter.Position = pos3D;
            newFighter.CurrentPosition = pos3D;
            newFighter.Team = team;
            gameWord.ListPlayers[team].Add(newFighter);
            if (isPlayerControl)
            {
                Aura aura = new Aura(Game.Content, @"Resources/Aura/aura1", 2f, Vector3.Zero, Matrix.CreateRotationX(-MathHelper.PiOver2));
                newFighter.Aura = aura;
                _team = team;
                player = newFighter;
            }
            else
            {
                if (level == 0)
                {
                    computerAIControl.Add(new NoobControl(newFighter, team));
                }
                else if (level == 1)
                {
                    computerAIControl.Add(new ProControl(newFighter, team));
                }
                else
                {
                    computerAIControl.Add(new ProControl(newFighter, team));
                }
            }
            ParticleSystem shield = new EnergyShieldParticle(Game, Game.Content);
            shield.DrawOrder = 600;
            Game.Components.Add(shield);
            newFighter.EnergyShield = shield;
            string[] footSteps = { @"Resources/SoundsEffect/footsteps1", @"Resources/SoundsEffect/footsteps1" };
            newFighter.FootStepSound = Game.Content.Load<SoundEffect>(footSteps[gameRandom.Next() % footSteps.Length]);

            string[] explosions = { @"Resources/SoundsEffect/Explosion7"};
            newFighter.ExplosionSound = Game.Content.Load<SoundEffect>(explosions[gameRandom.Next() % explosions.Length]);

            string[] hitSounds = { @"Resources/SoundsEffect/punch1", @"Resources/SoundsEffect/punch2", @"Resources/SoundsEffect/punch3" };
            newFighter.HitSound = Game.Content.Load<SoundEffect>(hitSounds[gameRandom.Next() % hitSounds.Length]);
        }

        public void initMap(string mapName)
        {
            _mapInfo = Game.Content.Load<MapInfo>(@"Resources/Map/" + mapName + @"/MapInfo");
            skyDom = new My3DModel(Game.Content, _mapInfo.Path + @"/Sky", _mapInfo.ScaleSky, Vector3.Zero, 0);
            terrainMap = new Map(Game.Content, _mapInfo.Path + @"/HeightMap", _mapInfo.ScaleMap, new Vector3(0, 0, 0), 0);
            terrainMap.setMapInfo(_mapInfo);
            gameWord = new Word(terrainMap, 2);

            float x = _mapInfo.X + _mapInfo.Width / 2;
            float y = _mapInfo.Y + _mapInfo.Height / 2; 

            motionCamera.initCamera(

                new Vector3(x, 300, y),
                new Vector3(x, 0, y),
                new Vector3(0, 0, 1),
                1f,
                1000f,
                MathHelper.PiOver4,
                widthScreen / heightScreen
                );
        }
        #endregion

        #region Update
        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            base.Update(gameTime);

            UpdatePlaying(gameTime);
            //updateParticle3DEffect(gameTime);
            updateParticleCameraInfo();
        }

        private void updateParticleCameraInfo()
        {
            for (int i = 0; i < _teamA.Count; i++)
            {
                _teamA[i].EnergyShield.SetCamera(camera.View, camera.Projection);
                for (int j = 0; j < _teamA[i].EnergySpheres.Count; j++)
                {
                    _teamA[i].EnergySpheres[j].Sphere.SetCamera(camera.View, camera.Projection);
                    _teamA[i].EnergySpheres[j].Explosion.SetCamera(camera.View, camera.Projection);
                }
            }
            for (int i = 0; i < _teamB.Count; i++)
            {
                _teamB[i].EnergyShield.SetCamera(camera.View, camera.Projection);
                for (int j = 0; j < _teamB[i].EnergySpheres.Count; j++)
                {
                    _teamB[i].EnergySpheres[j].Sphere.SetCamera(camera.View, camera.Projection);
                    _teamB[i].EnergySpheres[j].Explosion.SetCamera(camera.View, camera.Projection);
                }
            }
        }

        #region Update Particle 3D Effect
        private void updateParticle3DEffect(GameTime gameTime)
        {
            switch (currentState)
            {
                case PARTICLE_STATE.EXPLOSION:
                    UpdateExplosions(gameTime);
                    break;

                case PARTICLE_STATE.SMOKE_PLUME:
                    UpdateSmokePlume();
                    break;

                case PARTICLE_STATE.RING_OF_FIRE:
                    UpdateFire();
                    break;

                case PARTICLE_STATE.SHIELD:
                    UpdateShield();
                    break;
            }

            UpdateProjectiles(gameTime);
            updateParticle3DEffectCameraInfo();
        }

        private void UpdateShield()
        {
            const int fireParticlesPerFrame = 20;

            // Create a number of fire particles, randomly positioned around a circle.
            for (int i = 0; i < fireParticlesPerFrame; i++)
            {
                //for (int j = 0; j < _teamA.Count; i++)
                //    shieldParticles.AddParticle(_teamA[j].Position, Vector3.Zero);
                //for (int j = 0; j < _teamB.Count; i++)
                //    shieldParticles.AddParticle(_teamB[j].Position, Vector3.Zero);
            }
        }

        private void updateParticle3DEffectCameraInfo()
        {
            // Pass camera matrices through to the particle system components.
            explosionParticles.SetCamera(camera.View, camera.Projection);
            explosionSmokeParticles.SetCamera(camera.View, camera.Projection);
            projectileTrailParticles.SetCamera(camera.View, camera.Projection);
            smokePlumeParticles.SetCamera(camera.View, camera.Projection);
            fireParticles.SetCamera(camera.View, camera.Projection);
            shieldParticles.SetCamera(camera.View, camera.Projection);
        }

        /// <summary>
        /// Helper for updating the explosions effect.
        /// </summary>
        void UpdateExplosions(GameTime gameTime)
        {
            timeToNextProjectile -= gameTime.ElapsedGameTime;

            if (timeToNextProjectile <= TimeSpan.Zero)
            {
                // Create a new projectile once per second. The real work of moving
                // and creating particles is handled inside the Projectile class.
                projectiles.Add(new Projectile(explosionParticles,
                                               explosionSmokeParticles,
                                               projectileTrailParticles));

                timeToNextProjectile += TimeSpan.FromSeconds(1);
            }
        }

        /// <summary>
        /// Helper for updating the list of active projectiles.
        /// </summary>
        void UpdateProjectiles(GameTime gameTime)
        {
            int i = 0;

            while (i < projectiles.Count)
            {
                if (!projectiles[i].Update(gameTime))
                {
                    // Remove projectiles at the end of their life.
                    projectiles.RemoveAt(i);
                }
                else
                {
                    // Advance to the next projectile.
                    i++;
                }
            }
        }


        /// <summary>
        /// Helper for updating the smoke plume effect.
        /// </summary>
        void UpdateSmokePlume()
        {
            // This is trivial: we just create one new smoke particle per frame.
            smokePlumeParticles.AddParticle(Vector3.Zero, Vector3.Zero);
        }


        /// <summary>
        /// Helper for updating the fire effect.
        /// </summary>
        void UpdateFire()
        {
            const int fireParticlesPerFrame = 20;

            // Create a number of fire particles, randomly positioned around a circle.
            for (int i = 0; i < fireParticlesPerFrame; i++)
            {
                fireParticles.AddParticle(RandomPointOnCircle(), Vector3.Zero);
            }

            // Create one smoke particle per frmae, too.
            smokePlumeParticles.AddParticle(RandomPointOnCircle(), Vector3.Zero);
        }

        private Vector3 RandomPointOnSphere()
        {
            const float radius = 1f;
            const float height = 40;

            double angle1 = gameRandom.NextDouble() * Math.PI * 2;
            double angle2 = gameRandom.NextDouble() * Math.PI * 2;

            float x = (float)(Math.Cos(angle1) * Math.Sin(angle2));
            float y = (float)(Math.Sin(angle1) * Math.Sin(angle2));
            float z = (float)(Math.Cos(angle2));

            //return new Vector3(x * radius, y * radius + height, radius * z);
            return player.Position;
        }

        /// <summary>
        /// Helper used by the UpdateFire method. Chooses a random location
        /// around a circle, at which a fire particle will be created.
        /// </summary>
        Vector3 RandomPointOnCircle()
        {
            const float radius = 30;
            const float height = 40;

            double angle = gameRandom.NextDouble() * Math.PI * 2;

            float x = (float)Math.Cos(angle);
            float y = (float)Math.Sin(angle);

            return new Vector3(x * radius, y * radius + height, 0);
        }
        #endregion

        private void UpdatePlaying(GameTime gameTime)
        {

            // Allows the game to exit
            gameRadar.Clear();
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                Game.Exit();

            // TODO: Add your update logic here

            HandleKeyBoardInput();
            HandleMouseInput(gameTime);


            if (gameState == GAME_STATE.BEGIN)
            {
                camera.Update(gameTime);
                if (motionCamera.isSettled())
                {
                    gameState = GAME_STATE.PLAY;
                    camera = thirdPersonCamera;
                }
                foreach (Fighter fighter in _teamA)
                {
                    fighter.Update(gameTime, terrainMap);
                }
                foreach (Fighter fighter in _teamB)
                {
                    fighter.Update(gameTime, terrainMap);
                }
                return;
            }
            else if (gameState != GAME_STATE.PLAY)
            {
                return;
            }
            
            
            foreach (ComputerControl aIControl in computerAIControl)
            {
                aIControl.UpdateAction(gameWord,Game);
            }

            camera.UpdateCameraInfo(player);
            camera.Update(gameTime);

            skyDom.Position = new Vector3(player.Position.X, -200, player.Position.Z);

            gameRadar.Rotation = -player.LookRotationY;
            gameRadar.RadarPosition = new Vector2(player.Position.X, player.Position.Z);
            Vector3 temp = player.CurrentPosition;
            temp.Y += 0.1f;
            for (int i = 0; i < _teamA.Count; i++)
            {
                if (_teamA[i].CurrentState == Fighter.State.dead)
                    continue;
                for (int j = 0; j < _teamB.Count; j++)
                {
                    if (_teamB[j].CurrentState == Fighter.State.dead)
                        continue;
                    _teamA[i].hit(_teamB[j], modeDamageRatio);
                    _teamB[j].hit(_teamA[i], modeDamageRatio);
                    if (_teamA[i].Hp == 0)
                    {
                        _teamA[i].Die++;
                        _teamB[j].Kill++;
                     
                    }
                    if (_teamB[j].Hp == 0)
                    {
                        _teamA[i].Kill++;
                        _teamB[j].Die++;
       
                    }
                    if (!_teamA[i].Tacked && !_teamB[j].Tacked)
                    {
                        Colision(_teamA[i], _teamB[j]);
                    }
                }
            }
            updateEnergySpheresCollisionState();
            for (int i = 0; i < _teamA.Count; i++)
            {
                _teamA[i].Update(gameTime, terrainMap);
                _teamA[i].PlaySoundEffects(player.CurrentPosition);
                if (_teamA[i].CurrentState == Fighter.State.dead)
                    continue;
                else if (_teamA[i].Hp == 0)
                {
                    _teamA[i].Dead();
                }

                gameRadar.addPosition(new Vector2(_teamA[i].Position.X, _teamA[i].Position.Z));
                for (int j = i + 1; j < _teamA.Count; j++)
                {
                    if (_teamA[j].CurrentState != Fighter.State.dead)
                        Colision(_teamA[i], _teamA[j]);
                }
            }
            for (int i = 0; i < _teamB.Count; i++)
            {
                _teamB[i].Update(gameTime, terrainMap);
                _teamB[i].PlaySoundEffects(player.CurrentPosition);
                if (_teamB[i].CurrentState == Fighter.State.dead)
                    continue;
                else if (_teamB[i].Hp == 0)
                {
                    _teamB[i].Dead();
                    
                }
                
                gameRadar.addPosition(new Vector2(_teamB[i].Position.X, _teamB[i].Position.Z));
                for (int j = i + 1; j < _teamB.Count; j++)
                {
                    if(_teamB[j].CurrentState != Fighter.State.dead)
                        Colision(_teamB[i], _teamB[j]);
                }
            }

            terrainMap.Update(gameTime);
            hpBar.Value = (float)player.Hp / Fighter.MAX_HP;
            ppBar.Value = (float)player.Pp / Fighter.MAX_HP;

            
            updateTeamPoint();
            playingTime += gameTime.ElapsedGameTime.TotalMilliseconds;
            if ((limitSecondGameTime>0 && playingTime / 1000 >= limitSecondGameTime) || _teamAPoint >= _victoryPoint || _teamBPoint >= _victoryPoint)
            {
                gameState = GAME_STATE.END;
            }

        }
        private void updateTeamPoint()
        {
            _teamAPoint = 0;
            foreach (Fighter fighter in _teamA)
            {
                _teamAPoint += fighter.Kill;
            }
            _teamBPoint = 0;
            foreach (Fighter fighter in _teamB)
            {
                _teamBPoint += fighter.Kill;
            }
        }
        private void updateEnergySpheresCollisionState()
        {
            _explosionPoint.Clear();
            for (int i = 0; i < _teamA.Count; i++)
            {
                if (_teamA[i].CurrentState == Fighter.State.dead)
                    continue;
                for (int j = 0; j < _teamB.Count; j++)
                {
                    if (_teamB[j].CurrentState == Fighter.State.dead)
                        continue;
                   _teamA[i].isEnergySphereCollision(_teamB[j]);
                    _teamB[j].isEnergySphereCollision(_teamA[i]);
  
                    SetExplosion(_teamA[i],0);
                    SetExplosion(_teamB[j],1);
                }
            }
            
        }

        private void SetExplosion(Fighter firer, int team)
        {
            List<Vector3> exlposePoints = firer.getExplosionPoint();
            for (int i = 0; i < exlposePoints.Count; i++)
            {
                foreach(Fighter fighter in _teamA)
                {
                    SetExplose(exlposePoints[i],firer,fighter,(team == 0));
                }
                foreach (Fighter fighter in _teamB)
                {
                    SetExplose(exlposePoints[i], firer, fighter, (team == 1));
                }
            }
            
            
        }

        private void SetExplose(Vector3 exlposePoint, Fighter firer, Fighter fighter,bool isFriend)
        {
            if (fighter.Hp > 0)
            {
                Vector3 dPos = fighter.CurrentPosition - exlposePoint;
                dPos.Y = 1;
                float d = dPos.Length();
                if (d < EnergySphere.EXPLOSE_RANGE)
                {
                    d = (EnergySphere.EXPLOSE_RANGE * EnergySphere.EXPLOSE_RANGE - d * d)/10;
                    fighter.Hurt();
                    fighter.Hp -= (int)(d/5);
                    fighter.setForce(dPos, d);
                    if (fighter.Hp == 0)
                    {
                        if (isFriend)
                        {
                          
                            fighter.Die++;
                        }
                        else
                        {
                            firer.Kill++;
                            fighter.Die++;
                        }
                    }
                }
            }
        }
        #endregion

        #region Draw
        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
            DrawPlayingMode(gameTime);
        }


        private void DrawPlayingMode(GameTime gameTime)
        {
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState = BlendState.NonPremultiplied;
            GraphicsDevice.Clear(Color.White);
            GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
            skyDom.DrawWithFog(gameTime, GraphicsDevice, null, camera, 300, 500);
            GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;

            terrainMap.Draw(gameTime, GraphicsDevice, effect, camera);


            for (int i = 0; i < _teamA.Count; i++)
            {
                _teamA[i].Draw(gameTime, GraphicsDevice, effect, camera);
                if (modeDrawingBoundingSphere)
                    _teamA[i].DrawBoundingSpheres(GraphicsDevice, camera.View, camera.Projection);
            }
            for (int i = 0; i < _teamB.Count; i++)
            {
                _teamB[i].Draw(gameTime, GraphicsDevice, effect, camera);
                if (modeDrawingBoundingSphere)
                    _teamB[i].DrawBoundingSpheres(GraphicsDevice, camera.View, camera.Projection);
            }
            //aura.Draw(gameTime, GraphicsDevice, effect, camera);

            spriteBatch.Begin();

          
            Vector2 inforPosition = new Vector2(widthScreen - 200,heightScreen - 100);
            gameRadar.Draw(gameTime, spriteBatch, new Rectangle(5, 5, heightScreen / 4, heightScreen / 4));
            int seconds = limitSecondGameTime - (int)playingTime/1000;
            seconds = Math.Abs(seconds);
            string  infor = "TIME LEFT: " 
                + (seconds/60).ToString("00")
                + " : "
                + (seconds % 60).ToString("00")
                + "\nANGLE TEAM - "
                + _teamAPoint.ToString()
                + "\nDEMON TEAM - "
                + _teamBPoint.ToString();
            spriteBatch.DrawString(font, infor, new Vector2(inforPosition.X+1, inforPosition.Y +1), Color.Black);
            spriteBatch.DrawString(font, infor, new Vector2(inforPosition.X-1, inforPosition.Y -1), Color.White);
            
            spriteBatch.DrawString(font, infor, inforPosition, Color.Green);
            int r = heightScreen / 8;
            int r2 = r * 3 / 2;
            hpBar.Draw(gameTime, spriteBatch, new Rectangle(10, heightScreen - r - 10, r, r));
            ppBar.Draw(gameTime, spriteBatch, new Rectangle(10 + r / 6, heightScreen - r / 6 - r2 - 10, r2, r2));
            aimCursor.Draw(gameTime, spriteBatch);

            if (gameState == GAME_STATE.PAUSE)
            {


                panel.Draw(gameTime, spriteBatch);
                spriteBatch.DrawString(font, "Exit game ?", new Vector2(widthScreen / 2 - 68, heightScreen / 2 - 70), Color.White);
                yesButton.Draw(gameTime, spriteBatch);
                noButton.Draw(gameTime, spriteBatch);
            }
            else if (isTabPressed || gameState == GAME_STATE.END)
            {
                DrawPointTable(gameTime, spriteBatch, tableStart1, tableStart2, tableTab1, tableTab2);
                if (gameState == GAME_STATE.END)
                {
                    if (_teamAPoint == _teamBPoint)
                    {
                        reSultSprite = new Sprite2D(Game.Content, @"Resources/InGame2DResources/Draw", new Vector2(widthScreen / 2, heightScreen / 2), true);
                    }
                    else if ((_team == 0 && _teamAPoint < _teamBPoint) || (_team == 1 && _teamAPoint > _teamBPoint))
                    {
                        reSultSprite = new Sprite2D(Game.Content, @"Resources/InGame2DResources/Lose", new Vector2(widthScreen / 2, heightScreen / 2), true);
                    }
                    reSultSprite.Draw(gameTime, spriteBatch);
                }
            }
            
            cursor.Draw(gameTime, spriteBatch);
            spriteBatch.End();


        }

        public void DrawPointTable(GameTime gameTime, SpriteBatch spriteBatch,Vector2 startPoint1, Vector2 startPoint2 , Vector2 tab1, Vector2 tab2)
        {
            tablePanel.Draw(gameTime, spriteBatch);

            spriteBatch.DrawString(font,"Die", tab1, Color.White);
            spriteBatch.DrawString(font, "Kill", tab2, Color.White);
            int x = (int)startPoint1.X;
            int y = (int)startPoint1.Y;
            int h = font.LineSpacing;
            spriteBatch.DrawString(font, "Angle Team", new Vector2(x, y), Color.White);
            spriteBatch.DrawString(font, _teamAPoint.ToString(), new Vector2(tab2.X,y), Color.White);
            x += 10;
            Color drawColor = Color.White;
            for (int i = 0; i < _teamA.Count; i++)
            {
                if (_teamA[i] == player)
                {
                    drawColor = new Color(1,0.5f,0.5f,0.5f);
                }
                else
                {
                    drawColor = Color.White;
                }
                y += h;
                spriteBatch.DrawString(font, _teamA[i].Name, new Vector2(x, y), drawColor, 0, Vector2.Zero, 0.9f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, _teamA[i].Die.ToString(), new Vector2(tab1.X, y), drawColor, 0, Vector2.Zero, 0.9f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, _teamA[i].Kill.ToString(), new Vector2(tab2.X, y), drawColor, 0, Vector2.Zero, 0.9f, SpriteEffects.None, 0);
            }

            x = (int)startPoint2.X;
            y = (int)startPoint2.Y;
            
            spriteBatch.DrawString(font, "Demon Team", new Vector2(x, y), Color.White);
            spriteBatch.DrawString(font, _teamBPoint.ToString(), new Vector2(tab2.X, y), Color.White);
            x += 10;
            for (int i = 0; i < _teamB.Count; i++)
            {
                if (_teamB[i] == player)
                {
                    drawColor = new Color(1, 0.5f, 0.5f, 0.5f);
                }
                else
                {
                    drawColor = Color.White;
                }
                y += h;
                spriteBatch.DrawString(font, _teamB[i].Name, new Vector2(x, y), drawColor, 0, Vector2.Zero, 0.9f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, _teamB[i].Die.ToString(), new Vector2(tab1.X, y), drawColor, 0, Vector2.Zero, 0.9f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, _teamB[i].Kill.ToString(), new Vector2(tab2.X, y), drawColor, 0, Vector2.Zero, 0.9f, SpriteEffects.None, 0);
            }

        }
        #endregion

        #region Handle KeyBoard Input

        /// <summary>
        /// Handles input for quitting the game.
        /// </summary>
        /// 
        private void HandleKeyBoardInput()
        {

            currentKeyboardState = Keyboard.GetState();
            if ((currentKeyboardState.IsKeyUp(Keys.Escape)) && escPressed)
            {

                if (gameState == GAME_STATE.PLAY)
                {
                    PauseGame();
                }
                else if (gameState == GAME_STATE.PAUSE)
                {
                    ResumeGame();
                }
                else if (gameState == GAME_STATE.END)
                {
                    QuitGame();
                }
                escPressed = false;

            }
            escPressed = currentKeyboardState.IsKeyDown(Keys.Escape);
            isTabPressed = currentKeyboardState.IsKeyDown(Keys.Tab);

            if (gameState != GAME_STATE.PLAY)
                return;

            currentKeyboardState = Keyboard.GetState();
            currentGamePadState = GamePad.GetState(PlayerIndex.One);
            if (currentKeyboardState.IsKeyDown(Keys.Enter))
            {
                isBoundingKeyClicked = true;
            }
            if (currentKeyboardState.IsKeyUp(Keys.Enter) && isBoundingKeyClicked)
            {
                modeDrawingBoundingSphere = !modeDrawingBoundingSphere;
                isBoundingKeyClicked = false;
            }
            Global.keyBoardMapping.upDateKeys();

            KeyBoardMapping keyMap = Global.keyBoardMapping;
            List<KeyBoardMapping.GameKeys> newGameKeys = Global.keyBoardMapping.NewGameKeysPressed;

            if (Global.keyBoardMapping.isJustReleased(KeyBoardMapping.GameKeys.Jump))
            {
                player.Jump();
                //catFighter.setHeight(100);
            }
            if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Defend))
            {
                player.Defend();
            }
            else if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Up))
            {
                player.Run();
                if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Left))
                {
                    player.RunRotation = -MathHelper.PiOver4;
                }
                else if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Right))
                {
                    player.RunRotation = MathHelper.PiOver4;
                }
                else
                {
                    player.RunRotation = 0;
                }
            }
            else if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Down))
            {
                player.Run();
                if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Left))
                {
                    player.RunRotation = -3 * MathHelper.PiOver4;
                }
                else if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Right))
                {
                    player.RunRotation = 3 * MathHelper.PiOver4;
                }
                else
                {
                    player.RunRotation = MathHelper.Pi;
                }
            }
            else if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Left))
            {
                player.Run();
                player.RunRotation = -MathHelper.PiOver2;
            }
            else if (keyMap.isGameKeyPress(KeyBoardMapping.GameKeys.Right))
            {
                player.Run();
                player.RunRotation = MathHelper.PiOver2;
            }
            else
            {
                player.Idle();
            }

            if (currentKeyboardState.IsKeyDown(Keys.D1))
                isNumber1Pressed = true;
            else if (currentKeyboardState.IsKeyDown(Keys.D3))
                isNumber3Pressed = true;
            if (currentKeyboardState.IsKeyUp(Keys.D1) && isNumber1Pressed)
            {
                isNumber1Pressed = false;
                setCamera(CAMERA_TYPE.FIRST_PERSON);
            }
            else if (currentKeyboardState.IsKeyUp(Keys.D3) && isNumber3Pressed)
            {
                isNumber3Pressed = false;
                setCamera(CAMERA_TYPE.THIRD_PERSON);
            }
            player.IsFired = Global.keyBoardMapping.isGameKeyPress(KeyBoardMapping.GameKeys.Power);
        }
        
        bool isNumber3Pressed = false;
        bool isNumber1Pressed = false;

        /// <summary>
        /// Handles camera input.
        /// </summary>



        #endregion

        #region Handle Mouse Input

        private void HandleMouseInput(GameTime gameTime)
        {
            currentTimeThrowEnergySphere += gameTime.ElapsedGameTime.Milliseconds;
            MouseState ms = Mouse.GetState();
            if (isDraggedLeftMouse)
                timeDragLeftMouse += gameTime.ElapsedGameTime.Milliseconds;
            if (flag)
            {
                flag = false;
                preScrollWheelValue = ms.ScrollWheelValue;
            }

            int x = ms.X - GraphicsDevice.Viewport.Width / 2;
            int y = ms.Y - GraphicsDevice.Viewport.Height / 2;

            if (gameState == GAME_STATE.PLAY && (cameraType == CAMERA_TYPE.THIRD_PERSON))
            {

                if (!isDraggedMidMouse)
                {
                    if (x != 0)
                        player.LookRotationY -= x * Global.mouseSpeed;
                    if (y != 0)
                        player.LookRotationZ -= y * Global.mouseSpeed;
                }
                else
                {
                    if (x != 0)
                        rotationCamera.RotationY -= x * Global.mouseSpeed;
                    if (y != 0)
                        rotationCamera.RotationY -= y * Global.mouseSpeed;
                }
                Mouse.SetPosition(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
            }
            else if (cameraType == CAMERA_TYPE.ROTATION)
            {
                if (x != 0)
                    rotationCamera.RotationY -= x * Global.mouseSpeed;
                if (y != 0)
                    rotationCamera.LookRotationY -= y * Global.mouseSpeed;
                Mouse.SetPosition(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
            }
            else if (cameraType == CAMERA_TYPE.FIRST_PERSON)
            {
                if (x != 0)
                    player.LookRotationY -= x * Global.mouseSpeed;
                if (y != 0)
                    player.LookRotationZ -= y * Global.mouseSpeed;
                Mouse.SetPosition(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
            }

            if (gameState == GAME_STATE.PAUSE)
            {
                cursor.Position = new Vector2(ms.X, ms.Y);
                if (yesButton.isHover(cursor.Position))
                {
                    if (ms.LeftButton == ButtonState.Pressed)
                    {
                        if (isDraggedLeftMouse == false) // Bat dau an trai chuot
                        {
                            isDraggedLeftMouse = true;
                        }
                    }
                    else
                    {
                        if (isDraggedLeftMouse == true) // Bat dau tha trai chuot ra
                        {
                            QuitGame();
                        }
                    }
                    yesButton.FilterColor = hoverButtonColor;
                }
                else
                {
                    yesButton.FilterColor = buttonColor;
                }
                if (noButton.isHover(cursor.Position))
                {
                    noButton.FilterColor = hoverButtonColor;
                    if (ms.LeftButton == ButtonState.Pressed)
                    {
                        if (isDraggedLeftMouse == false) // Bat dau an trai chuot
                        {
                            isDraggedLeftMouse = true;
                        }
                    }
                    else
                    {
                        if (isDraggedLeftMouse == true) // Bat dau tha trai chuot ra
                        {
                            ResumeGame();
                        }
                    }
                }
                else
                {
                    noButton.FilterColor = buttonColor;
                }

                return;
            }
            int temp = ms.ScrollWheelValue - preScrollWheelValue;
            if (temp > 0)
            {
                if (camera.ZoomRate > 6)
                    camera.ZoomRate -= (float)Math.Abs(temp) / 50;
            }
            else if (temp < 0)
            {
                if (camera.ZoomRate < 30)
                    camera.ZoomRate += (float)Math.Abs(temp) / 50;
            }
            preScrollWheelValue = ms.ScrollWheelValue;
            if (ms.LeftButton == ButtonState.Pressed)
            {
                if (isDraggedLeftMouse == false) // Bat dau an trai chuot
                {
                    isDraggedLeftMouse = true;
                }
            }
            else
            {
                if (isDraggedLeftMouse == true) // Bat dau tha trai chuot ra
                {
                    isDraggedLeftMouse = false;

                    if (Global.keyBoardMapping.isGameKeyPress(KeyBoardMapping.GameKeys.Power))
                    {
                        if (currentTimeThrowEnergySphere > timeSpanThrowEnergySphere)
                        {
                            player.EnergySpheres.Add(new EnergySphere(Game));
                            player.ThrowEnergySphere(camera.CameraTarget);
                            currentTimeThrowEnergySphere = 0;
                        }
                    }
                    else
                    {
                        player.AddToComboQueue(Move.Strike.PUNCH);
                        player.Actack();
                    }
                    timeDragLeftMouse = 0;
                }
            }

            if (ms.RightButton == ButtonState.Pressed)
            {
                if (isDraggedLeftMouse == false) // Bat dau an trai chuot
                {
                    isDraggedRightMouse = true;
                }
            }
            else
            {
                if (isDraggedRightMouse == true) // Bat dau tha trai chuot ra
                {
                    isDraggedRightMouse = false;
                    player.AddToComboQueue(Move.Strike.KICK);
                    player.Actack();
                }
            }

            if (ms.MiddleButton == ButtonState.Pressed)
            {
                if (isDraggedMidMouse == false) // Bat dau an giua chuot
                {
                    isDraggedMidMouse = true;
                    setCamera(CAMERA_TYPE.ROTATION);
                }
            }
            else
            {
                if (isDraggedMidMouse == true) // Bat dau tha giua chuot ra
                {
                    isDraggedMidMouse = false;
                    setCamera(CAMERA_TYPE.THIRD_PERSON);
                }
            }
        }

        private void QuitGame()
        {
            Game.Components.Clear();
            Global.gameMode = Global.GAME_MODE.MAIN_MENU;
            Game.Components.Add(new MenuScreen(Game));
        }

        #endregion

        #region Other methods
        public void PauseGame()
        {
            gameState = GAME_STATE.PAUSE;
            cursor.Visible = true;
        }
        public void ResumeGame()
        {
            gameState = GAME_STATE.PLAY;
            cursor.Visible = false;
        }
        public void StartGame()
        {
            gameState = GAME_STATE.BEGIN;
            cursor.Visible = false;
            camera.UpdateCameraInfo(player);
            motionCamera.setNewInfor(camera.CameraPosition, camera.CameraTarget, camera.CameraUpVector, 100);
            camera = motionCamera;
        }
        public void Colision(Fighter fighter1, Fighter fighter2)
        {
            if (fighter1.isCollision(fighter2))
            {
                Vector3 dPos = fighter2.CurrentPosition - fighter1.CurrentPosition;
                dPos.Y = 0;

                float d = 7.5f - dPos.Length() * 2;
                if (dPos.Length() == 0)
                    dPos.X = 1;
                fighter2.setForce(dPos, d);
                fighter1.setForce(-dPos, d);
            }
        }



        public void setCamera(CAMERA_TYPE type)
        {
            switch (type)
            {
                case CAMERA_TYPE.THIRD_PERSON:
                    cameraType = CAMERA_TYPE.THIRD_PERSON;
                    thirdPersonCamera.ZoomRate = camera.ZoomRate;
                    camera = thirdPersonCamera;
                    break;
                case CAMERA_TYPE.ROTATION:
                    cameraType = CAMERA_TYPE.ROTATION;
                    rotationCamera.CameraTarget = camera.CameraTarget;
                    rotationCamera.ZoomRate = camera.ZoomRate;
                    camera = rotationCamera;
                    break;
                case CAMERA_TYPE.AUTO_ROTATION:
                    cameraType = CAMERA_TYPE.AUTO_ROTATION;
                    autoRotationCamera.RotationY = 0;
                    autoRotationCamera.ZoomRate = camera.ZoomRate;
                    camera = autoRotationCamera;
                    break;
                case CAMERA_TYPE.FIRST_PERSON:
                    cameraType = CAMERA_TYPE.FIRST_PERSON;
                    camera = firstPersonCamera;
                    break;
            }
        }
        #endregion
    }
}
